package cn.fintecher.pangolin.service.dataimp.service;

import cn.fintecher.pangolin.common.enums.BaseStatus;
import cn.fintecher.pangolin.common.enums.TaskBoxStatus;
import cn.fintecher.pangolin.common.enums.TaskBoxType;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.TaskBoxModel;
import cn.fintecher.pangolin.common.model.UploadFile;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.*;
import cn.fintecher.pangolin.entity.mysql.CaseInfo;
import cn.fintecher.pangolin.entity.mysql.QSysParam;
import cn.fintecher.pangolin.entity.mysql.SysParam;
import cn.fintecher.pangolin.service.dataimp.elastic.BaseCaseElastic;
import cn.fintecher.pangolin.service.dataimp.elastic.ExportTemplateElastic;
import cn.fintecher.pangolin.service.dataimp.elastic.OtherRecordElastic;
import cn.fintecher.pangolin.service.dataimp.elastic.PersonalContactElastic;
import cn.fintecher.pangolin.service.dataimp.model.request.ExportCaseRequest;
import cn.fintecher.pangolin.service.dataimp.model.request.ExportDistributeRequest;
import cn.fintecher.pangolin.service.dataimp.model.request.ExportWorkOrderRequest;
import cn.fintecher.pangolin.service.dataimp.repository.CaseFollowupRecordRepository;
import cn.fintecher.pangolin.service.dataimp.repository.CaseInfoRepository;
import cn.fintecher.pangolin.service.dataimp.repository.HistoryCasesRepository;
import cn.fintecher.pangolin.service.dataimp.repository.SysParamRepository;
import cn.fintecher.pangolin.service.dataimp.task.*;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 17:56 2019/10/15
 */

@Service("dataExportService")
@Transactional(rollbackFor = Exception.class)
public class DataExportService {
    @Autowired
    private BaseService baseService;

    @Autowired
    private ExportTemplateElastic exportTemplateElastic;

    @Autowired
    private OtherRecordElastic otherRecordElastic;

    @Autowired
    private ExportWorkOrderTask exportWorkOrderTask;

    @Autowired
    private BaseCaseElastic baseCaseElastic;

    @Autowired
    private CaseInfoRepository caseInfoRepository;

    @Autowired
    private HistoryCasesRepository historyCasesRepository;

    @Autowired
    private ExportCaseTask exportCaseTask;

    @Autowired
    private CaseFollowupRecordRepository caseFollowupRecordRepository;

    @Autowired
    private ExportFollowRecordTask exportFollowRecordTask;

    @Autowired
    private PersonalContactElastic personalContactElastic;

    @Autowired
    private ExportContactTask exportContactTask;

    @Autowired
    private SysParamRepository sysParamRepository;

    @Autowired
    private ExportDistributeTask exportDistributeTask;

    /**
     * 工单导出
     */
    public void exportWorkOrder(ExportWorkOrderRequest request, String token) {
        UserModel userModel = baseService.getUserByToken(token);
        TaskBoxModel model = baseService.getTaskBox(TaskBoxType.EXPORT, "工单导出", userModel);
        baseService.sendTaskBoxMessage(model, TaskBoxType.EXPORT, TaskBoxStatus.UN_FINISH, null, null, userModel, ZWDateUtil.getNowDateTime(), null, "工单导出");
        ExportTemplate exportTemplate = exportTemplateElastic.findById(request.getTemplateId()).orElseThrow(() -> new BadRequestException(null, "template", "template.is.null"));
        BoolQueryBuilder builder = request.getBuilder();
        Iterable<OtherRecord> iterable = otherRecordElastic.search(builder);
        exportWorkOrderTask.exportWorkOrder(IterableUtils.toList(iterable), exportTemplate, model, userModel);
    }

    /**
     * 案件导出
     */
    public void exportCase(ExportCaseRequest request, String token) {
        UserModel userModel = baseService.getUserByToken(token);
        TaskBoxModel model = baseService.getTaskBox(TaskBoxType.EXPORT, "案件信息导出", userModel);
        baseService.sendTaskBoxMessage(model, TaskBoxType.EXPORT, TaskBoxStatus.UN_FINISH, null, null, userModel, ZWDateUtil.getNowDateTime(), null, "案件信息导出");
        ExportTemplate exportTemplate = exportTemplateElastic.findById(request.getTemplateId()).orElseThrow(() -> new BadRequestException(null, "template", "template.is.null"));
        switch (request.getType()) {
            case "WAIT_DISTRIBUTE":
                BoolQueryBuilder builder1 = request.getESBuilder();
                Iterable<BaseCase> baseCases = baseCaseElastic.search(builder1);
                exportCaseTask.exportBaseCase(IterableUtils.toList(baseCases), exportTemplate, model, userModel);
                break;
            case "RETURN":
            case "DELETE":
                BoolQueryBuilder builder2 = request.getESBuilder();
                Iterable<HistoryCases> historyCases = historyCasesRepository.search(builder2);
                exportCaseTask.exportHistoryCase(IterableUtils.toList(historyCases), exportTemplate, model, userModel);
                break;
            case "DEPARTMENT":
            case "COLLECTING":
            case "PUBLIC":
            case "STOPPING":
                BooleanBuilder builder3 = request.getSqlBuilder();
                Iterable<CaseInfo> caseInfos = caseInfoRepository.findAll(builder3);
                exportCaseTask.exportCaseInfo(IterableUtils.toList(caseInfos), exportTemplate, model, userModel);
                break;
        }
    }

    /**
     * 导出催记
     */
    public void exportFollowRecord(ExportCaseRequest request, String token) {
        UserModel userModel = baseService.getUserByToken(token);
        TaskBoxModel model = baseService.getTaskBox(TaskBoxType.EXPORT, "催记导出", userModel);
        baseService.sendTaskBoxMessage(model, TaskBoxType.EXPORT, TaskBoxStatus.UN_FINISH, null, null, userModel, ZWDateUtil.getNowDateTime(), null, "催记导出");
        ExportTemplate exportTemplate = exportTemplateElastic.findById(request.getTemplateId()).orElseThrow(() -> new BadRequestException(null, "template", "template.is.null"));
        List<CaseFollowupRecord> records = new ArrayList<>();
        BoolQueryBuilder builder = new BoolQueryBuilder();
        List<List<String>> caseIdList = new ArrayList<>();
        switch (request.getType()) {
            case "WAIT_DISTRIBUTE":
                BoolQueryBuilder builder1 = request.getESBuilder();
                Iterable<BaseCase> baseCases = baseCaseElastic.search(builder1);
                List<BaseCase> list = IterableUtils.toList(baseCases);
                if (list.size() <= 500) {
                    List<String> caseIds = new ArrayList<>();
                    list.forEach(e -> caseIds.add(e.getId()));
                    caseIdList.add(caseIds);
                } else {
                    int flag = (int) Math.ceil((double) list.size() / 500);
                    for (int i = 0; i <= flag; i++) {
                        Pageable pageable = PageRequest.of(i, 500);
                        List<BaseCase> list1 = list.stream().skip(pageable.getPageNumber() * pageable.getPageSize()).limit(pageable.getPageSize()).collect(Collectors.toList());
                        List<String> caseIds = new ArrayList<>();
                        list1.forEach(e -> caseIds.add(e.getId()));
                        caseIdList.add(caseIds);
                    }
                }
                caseIdList.forEach(e -> {
                    builder.must(QueryBuilders.termsQuery("caseId.keyword", e));
                    Iterable<CaseFollowupRecord> iterable = caseFollowupRecordRepository.search(builder);
                    records.addAll(IterableUtils.toList(iterable));
                });
                break;
            case "RETURN":
            case "DELETE":
                BoolQueryBuilder builder2 = request.getESBuilder();
                Iterable<HistoryCases> historyCases = historyCasesRepository.search(builder2);
                List<HistoryCases> historyCases1 = IterableUtils.toList(historyCases);
                if (historyCases1.size() <= 500) {
                    List<String> caseIds = new ArrayList<>();
                    historyCases1.forEach(e -> caseIds.add(e.getId()));
                    caseIdList.add(caseIds);
                } else {
                    int flag = (int) Math.ceil((double) historyCases1.size() / 500);
                    for (int i = 0; i <= flag; i++) {
                        Pageable pageable = PageRequest.of(i, 500);
                        List<HistoryCases> list1 = historyCases1.stream().skip(pageable.getPageNumber() * pageable.getPageSize()).limit(pageable.getPageSize()).collect(Collectors.toList());
                        List<String> caseIds = new ArrayList<>();
                        list1.forEach(e -> caseIds.add(e.getId()));
                        caseIdList.add(caseIds);
                    }
                }
                caseIdList.forEach(e -> {
                    builder.must(QueryBuilders.termsQuery("caseId.keyword", e));
                    Iterable<CaseFollowupRecord> iterable = caseFollowupRecordRepository.search(builder);
                    records.addAll(IterableUtils.toList(iterable));
                });
                break;
            case "DEPARTMENT":
            case "COLLECTING":
            case "PUBLIC":
            case "STOPPING":
                BooleanBuilder builder3 = request.getSqlBuilder();
                Iterable<CaseInfo> caseInfos = caseInfoRepository.findAll(builder3);
                List<CaseInfo> caseInfoList = IterableUtils.toList(caseInfos);
                if (caseInfoList.size() <= 500) {
                    List<String> caseIds = new ArrayList<>();
                    caseInfoList.forEach(e -> caseIds.add(e.getId()));
                    caseIdList.add(caseIds);
                } else {
                    int flag = (int) Math.ceil((double) caseInfoList.size() / 500);
                    for (int i = 0; i <= flag; i++) {
                        Pageable pageable = PageRequest.of(i, 500);
                        List<CaseInfo> list1 = caseInfoList.stream().skip(pageable.getPageNumber() * pageable.getPageSize()).limit(pageable.getPageSize()).collect(Collectors.toList());
                        List<String> caseIds = new ArrayList<>();
                        list1.forEach(e -> caseIds.add(e.getId()));
                        caseIdList.add(caseIds);
                    }
                }
                caseIdList.forEach(e -> {
                    builder.must(QueryBuilders.termsQuery("caseId.keyword", e));
                    Iterable<CaseFollowupRecord> iterable = caseFollowupRecordRepository.search(builder);
                    records.addAll(IterableUtils.toList(iterable));
                });
                break;
        }
        if (!records.isEmpty()) {
            exportFollowRecordTask.exportFollowRecord(records, exportTemplate, model, userModel);
        } else {
            String fileId = baseService.generateTxt(Collections.singletonList("催记信息为空"), Long.toString(new Date().getTime()));
            baseService.sendTaskBoxMessage(model, TaskBoxType.EXPORT, TaskBoxStatus.FAILURE, fileId, "催记信息为空", userModel, null, ZWDateUtil.getNowDateTime(), "催记导出");
        }
    }

    /**
     * 联系人导出
     */
    public void exportContact(ExportCaseRequest request, String token) {
        UserModel userModel = baseService.getUserByToken(token);
        TaskBoxModel model = baseService.getTaskBox(TaskBoxType.EXPORT, "联系人导出", userModel);
        baseService.sendTaskBoxMessage(model, TaskBoxType.EXPORT, TaskBoxStatus.UN_FINISH, null, null, userModel, ZWDateUtil.getNowDateTime(), null, "联系人导出");
        ExportTemplate exportTemplate = exportTemplateElastic.findById(request.getTemplateId()).orElseThrow(() -> new BadRequestException(null, "template", "template.is.null"));
        List<PersonalContact> contacts = new ArrayList<>();
        BoolQueryBuilder builder = new BoolQueryBuilder();
        List<List<String>> caseIdList = new ArrayList<>();
        switch (request.getType()) {
            case "WAIT_DISTRIBUTE":
                BoolQueryBuilder builder1 = request.getESBuilder();
                Iterable<BaseCase> baseCases = baseCaseElastic.search(builder1);
                List<BaseCase> list = IterableUtils.toList(baseCases);
                if (list.size() <= 500) {
                    List<String> caseIds = new ArrayList<>();
                    list.forEach(e -> caseIds.add(e.getId()));
                    caseIdList.add(caseIds);
                } else {
                    int flag = (int) Math.ceil((double) list.size() / 500);
                    for (int i = 0; i <= flag; i++) {
                        Pageable pageable = PageRequest.of(i, 500);
                        List<BaseCase> list1 = list.stream().skip(pageable.getPageNumber() * pageable.getPageSize()).limit(pageable.getPageSize()).collect(Collectors.toList());
                        List<String> caseIds = new ArrayList<>();
                        list1.forEach(e -> caseIds.add(e.getId()));
                        caseIdList.add(caseIds);
                    }
                }
                caseIdList.forEach(e -> {
                    builder.must(QueryBuilders.termsQuery("caseId.keyword", e));
                    Iterable<PersonalContact> iterable = personalContactElastic.search(builder);
                    contacts.addAll(IterableUtils.toList(iterable));
                });
                break;
            case "RETURN":
            case "DELETE":
                BoolQueryBuilder builder2 = request.getESBuilder();
                Iterable<HistoryCases> historyCases = historyCasesRepository.search(builder2);
                List<HistoryCases> historyCases1 = IterableUtils.toList(historyCases);
                if (historyCases1.size() <= 500) {
                    List<String> caseIds = new ArrayList<>();
                    historyCases1.forEach(e -> caseIds.add(e.getId()));
                    caseIdList.add(caseIds);
                } else {
                    int flag = (int) Math.ceil((double) historyCases1.size() / 500);
                    for (int i = 0; i <= flag; i++) {
                        Pageable pageable = PageRequest.of(i, 500);
                        List<HistoryCases> list1 = historyCases1.stream().skip(pageable.getPageNumber() * pageable.getPageSize()).limit(pageable.getPageSize()).collect(Collectors.toList());
                        List<String> caseIds = new ArrayList<>();
                        list1.forEach(e -> caseIds.add(e.getId()));
                        caseIdList.add(caseIds);
                    }
                }
                caseIdList.forEach(e -> {
                    builder.must(QueryBuilders.termsQuery("caseId.keyword", e));
                    Iterable<PersonalContact> iterable = personalContactElastic.search(builder);
                    contacts.addAll(IterableUtils.toList(iterable));
                });
                break;
            case "DEPARTMENT":
            case "COLLECTING":
            case "PUBLIC":
            case "STOPPING":
                BooleanBuilder builder3 = request.getSqlBuilder();
                Iterable<CaseInfo> caseInfos = caseInfoRepository.findAll(builder3);
                List<CaseInfo> caseInfoList = IterableUtils.toList(caseInfos);
                if (caseInfoList.size() <= 500) {
                    List<String> caseIds = new ArrayList<>();
                    caseInfoList.forEach(e -> caseIds.add(e.getId()));
                    caseIdList.add(caseIds);
                } else {
                    int flag = (int) Math.ceil((double) caseInfoList.size() / 500);
                    for (int i = 0; i <= flag; i++) {
                        Pageable pageable = PageRequest.of(i, 500);
                        List<CaseInfo> list1 = caseInfoList.stream().skip(pageable.getPageNumber() * pageable.getPageSize()).limit(pageable.getPageSize()).collect(Collectors.toList());
                        List<String> caseIds = new ArrayList<>();
                        list1.forEach(e -> caseIds.add(e.getId()));
                        caseIdList.add(caseIds);
                    }
                }
                caseIdList.forEach(e -> {
                    builder.must(QueryBuilders.termsQuery("caseId.keyword", e));
                    Iterable<PersonalContact> iterable = personalContactElastic.search(builder);
                    contacts.addAll(IterableUtils.toList(iterable));
                });
                break;
        }
        if (!contacts.isEmpty()) {
            exportContactTask.exportFollowRecord(contacts, exportTemplate, model, userModel);
        } else {
            String fileId = baseService.generateTxt(Collections.singletonList("联系人导出异常"), Long.toString(new Date().getTime()));
            baseService.sendTaskBoxMessage(model, TaskBoxType.EXPORT, TaskBoxStatus.FAILURE, fileId, "联系人导出异常", userModel, null, ZWDateUtil.getNowDateTime(), "联系人导出");
        }
    }

    /**
     * 分案导出
     */
    public void exportDistribute(ExportDistributeRequest request, String token) {
        UserModel userModel = baseService.getUserByToken(token);
        TaskBoxModel model = baseService.getTaskBox(TaskBoxType.EXPORT, "分案导出", userModel);
        baseService.sendTaskBoxMessage(model, TaskBoxType.EXPORT, TaskBoxStatus.UN_FINISH, null, null, userModel, ZWDateUtil.getNowDateTime(), null, "分案导出");
        BooleanBuilder builder = request.getBuilder();
        Iterable<CaseInfo> iterable = caseInfoRepository.findAll(builder);
        SysParam sysParam = sysParamRepository.findOne(QSysParam.sysParam.code.eq("export.template")).orElseThrow(() -> new BadRequestException(null, "sysParam", "sysParam.is.null"));
        if (sysParam.getStatus().equals(BaseStatus.OFF)) {
            throw new BadRequestException(null, "sysParam", "sysParam.is.off");
        }
        if (StringUtils.isBlank(sysParam.getValue())) {
            throw new BadRequestException(null, "sysParam", "sysParam.value.is.null");
        }
        try {
            UploadFile uploadFile = baseService.getUploadFile(sysParam.getValue());
            exportDistributeTask.exportDistribute(IterableUtils.toList(iterable), uploadFile, model, userModel);
        } catch (Exception e) {
            e.printStackTrace();
            String id = baseService.generateTxt(Collections.singletonList("分案导出模板系统参数过期,请重新修改改参数"), ZWDateUtil.fomratterDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
            baseService.sendTaskBoxMessage(model, TaskBoxType.EXPORT, TaskBoxStatus.FAILURE, id, "分案导出", userModel, null, ZWDateUtil.getNowDateTime(), "分案导出");
        }
    }
}